﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace GameJamKingdom
{
    class Arena
    {
        
        // this is a change

        public int offset;
        public int scrollSpeed;
        public int scrollTime;
        public int pTime, sTime;

        Background background;
        public Character character;
        Texture2D wall;
        Texture2D brick;

        AnimatedComponent snakeBite;
        Rectangle snakeRect;

        public Random rand;

        Dictionary<string, GridObject> blockTypes;

        List<string[]> grid = new List<string[]>();

        public Arena(Game1 cGame)
        {
            background = new Background(cGame);
            character = new Character(cGame);
            rand = new Random();

            wall = cGame.Content.Load<Texture2D>("tempwall");
            brick = cGame.Content.Load<Texture2D>("BrickTile");

            snakeBite = new AnimatedComponent("snakeBiteAnim", "SnakeJaw", 5, 5, cGame);
            snakeRect = new Rectangle(Program.wWidth - 50, 0, 50, 600);

            offset = 0;
            scrollSpeed = 50;
            scrollTime = 0;
            pTime = -1;
            sTime = -1;

            blockTypes = new Dictionary<string, GridObject>();
            blockTypes.Add("empty", new EmptyBlock(cGame));
            blockTypes.Add("water", new WaterBlock(cGame));
            blockTypes.Add("lava", new LavaBlock(cGame));
            blockTypes.Add("brick", new BrickBlock(cGame));
            blockTypes.Add("coin", new CoinBlock(cGame));
            blockTypes.Add("spring", new SpringBlock(cGame));
            blockTypes.Add("hammer", new HammerBlock(cGame));
            blockTypes.Add("flipper", new FlipperBlock(cGame));
            blockTypes.Add("ice", new IceBlock(cGame));
            blockTypes.Add("time", new TimeBlock(cGame));

            for (int i = 0; i < Program.numColumns; i++)
            {
                AddColumn(cGame);
            }

            grid[3][5] = "empty";

            for (int i = 0; i < Program.numRows; i++)
                grid[0][i] = "lava";
        }

        public void move(string dir, int timePassed)
        {
            
            switch (dir)
            {
                case "right":
                    if ((int)character.gridPos.X < Program.numColumns - 1)
                    {
                        if (blockTypes[grid[(int)character.gridPos.X][(int)character.gridPos.Y]].testTime(character.getMode(), character.timeLastAction))
                        {
                            character.right();
                        }                          
                    }
                    break;
                case "left":
                    if ((int)character.gridPos.X > 0)
                    {
                        if (blockTypes[grid[(int)character.gridPos.X][(int)character.gridPos.Y]].testTime(character.getMode(), character.timeLastAction))
                        {
                            character.left();
                        }
                    }
                    break;
                case "up":
                    if ((int)character.gridPos.Y > 0)
                    {
                        if (blockTypes[grid[(int)character.gridPos.X][(int)character.gridPos.Y]].testTime(character.getMode(), character.timeLastAction))
                        {
                            character.up();
                        } 
                    }
                    break;
                case "down":
                    if ((int)character.gridPos.Y < Program.numRows - 1)
                    {
                        if (blockTypes[grid[(int)character.gridPos.X][(int)character.gridPos.Y]].testTime(character.getMode(), character.timeLastAction))
                        {
                            character.down();
                        } 
                    }
                    break;
            }
        }

        //bool legalMove(int xOffset, int yOffset)
        //{
        //    int newX = (int)character.gridPos.X + xOffset;
        //    int newY = (int)character.gridPos.Y + yOffset;
            
        //    // check top and bottom boundaries, can't move if we hit them
        //    if ((newY < 0) || (newY >= Program.numRows))
        //    {
        //        return false;
        //    }

        //    // TODO die if hit right or left column
        //    if ((newX <= 0) || (newX >= Program.numColumns - 2))
        //    {
        //        // game over
        //        return false;
        //    }

        //    // empty grid
        //    if (grid[(int)character.gridPos.X + xOffset][(int)character.gridPos.Y + yOffset].type.Equals("empty"))
        //    {
        //        if (character.timeLastAction > character.getMode().walkTime)
        //            return true;
        //    }
        //    // brick grid
        //    else if (grid[(int)character.gridPos.X][(int)character.gridPos.Y + 1].type.Equals("brick"))
        //    {
        //        if (character.timeLastAction > character.getMode().breakTime)
        //            return true;
        //    }
        //    // default case
        //    return false;
        //}

        public GridObject getBlock()
        {
            string temp;
            temp = grid[(int)character.gridPos.X][(int)character.gridPos.Y];
            GridObject blockTemp = blockTypes[temp];
            return blockTemp;
        }

        public void setBlock(string nType)
        {
            grid[(int)character.gridPos.X][(int)character.gridPos.Y] = nType;
        }

        public void tick(Game1 cGame, GameTime cTime)
        {
            if (pTime == -1)
            {
                pTime = (int)cTime.TotalGameTime.TotalSeconds;
                sTime = (int)cTime.TotalGameTime.TotalSeconds;
            }
            else
                pTime = (int)cTime.TotalGameTime.TotalSeconds;

            float timeDiff = pTime - sTime;


            if (timeDiff < 0)
                scrollSpeed = 50;
            else if (timeDiff >= 60)
                scrollSpeed = 10;
            else
            {
                scrollSpeed = (int)(((-1.0 / 90.0) * timeDiff * timeDiff) + 50);
            }           

            //change offset based on passed time
            scrollTime = scrollTime + cTime.ElapsedGameTime.Milliseconds;
            if (scrollTime > scrollSpeed)
            {
                scrollTime = 0;
                offset= offset+2;

                //generate new rows
                if (offset % (50) == 0)
                {
                    removeColumn();
                    AddColumn(cGame);

                    for (int i = 0; i < Program.numRows; i++)
                        grid[0][i] = "lava";

                    character.gridPos.X--;
                }
            }

            for (int i = 0; i < blockTypes.Count; i++)
            {
                blockTypes.ElementAt(i).Value.update(cTime);
            }

            // update snakeBite animation
            snakeBite.update(cTime);
        }

        void removeColumn()
        {
            grid.RemoveAt(0);
        }

        bool between(int randVal, int minVal, int MaxVal)
        {
            if (randVal >= minVal && randVal < MaxVal)
                return true;
            else
                return false;
        }

        void AddColumn(Game1 cGame)
        {
            Dictionary<string, int> blockCounts;
            blockCounts = new Dictionary<string, int>();
            blockCounts.Add("empty", 0);
            blockCounts.Add("water", 0);
            blockCounts.Add("lava", 0);
            blockCounts.Add("brick", 0);
            blockCounts.Add("coin", 0);
            blockCounts.Add("spring", 0);
            blockCounts.Add("hammer", 0);
            blockCounts.Add("flipper", 0);
            blockCounts.Add("ice", 0);
            blockCounts.Add("time", 0);

            Lottery bChooser = new Lottery(rand);
            bChooser.addMember("empty", 200);
            bChooser.addMember("water", 100);
            bChooser.addMember("lava", 40);
            bChooser.addMember("brick", 40);
            bChooser.addMember("coin", 16);
            bChooser.addMember("spring", 4);
            bChooser.addMember("hammer", 2);
            bChooser.addMember("flipper", 2);
            bChooser.addMember("ice", 60);
            bChooser.addMember("time", 1);
            
            string[] column = new string[Program.numRows];

            for (int j = 0; j < Program.numRows; j++)
            {
                column[j] = bChooser.pickWinner();
                blockCounts[column[j]]++;
                if (blockCounts[column[j]] > blockTypes[column[j]].maxPerColumn)
                    column[j] = "empty";
            }


            //for (int j = 0; j < Program.numRows; j++)
            //{
            //    //column[j] = new GridObject();

            //    int choice = rand.Next(100);

            //    if (between(choice, 0, 50))
            //    {
            //        column[j] = "empty";
            //        blockCounts["empty"]++;
            //    }
            //    if (between(choice, 50, 75))
            //    {
            //        column[j] = "water";
            //        blockCounts["water"]++;

            //        if (blockCounts["water"] > blockTypes["water"].maxPerColumn)
            //            column[j] = "empty";
            //    }
            //    if (between(choice, 75, 85))
            //    {
            //        column[j] = "coin";
            //        blockCounts["coin"]++;

            //        if (blockCounts["coin"] > blockTypes["coin"].maxPerColumn)
            //            column[j] = "empty";
            //    }
            //    if (between(choice, 85, 99))
            //    {
            //        column[j] = "lava";
            //        blockCounts["lava"]++;

            //        if (blockCounts["lava"] > blockTypes["lava"].maxPerColumn)
            //            column[j] = "empty";
            //    }
            //    if (between(choice, 99, 100))
            //    {
            //        column[j] = "hammer";
            //        blockCounts["hammer"]++;

            //        if (blockCounts["hammer"] > blockTypes["hammer"].maxPerColumn)
            //            column[j] = "empty";
            //    }
                
            //    //replace later with default empty block data               
            //}
            grid.Add(column);
        }

        public void render(SpriteBatch spriteBatch)
        {
            //render background
            background.render(spriteBatch, (offset%801));

            //render walls
            spriteBatch.Draw(wall, new Rectangle(0, 0, 800, 50), Color.DarkGray); // upper wall
            spriteBatch.Draw(wall, new Rectangle(0, 550, 800, 50), Color.DarkGray); // lower wall

            //render grid

            for (int i = 0; i < grid.Count; i++)
            {
                for (int j = 0; j < grid[i].Length; j++)
                {
                    blockTypes[grid[i][j]].render(new Rectangle(-(offset % 50) + (i * 50), 50 * (j + 1), 50, 50), spriteBatch);
                }
            }
            // render snake image
            snakeBite.render(snakeRect, spriteBatch);

            // render character
            character.render(spriteBatch, offset);

        }
    }
}
